package com.ssm.crud.controller;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ssm.crud.entities.Employee;
import com.ssm.crud.entities.Msg;
import com.ssm.crud.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2018/11/15 16:16
 */
@Slf4j
@Controller
public class EmployeeController {

    private final int PAGE_SIZE = 5;
    private final int NAVIGATE_PAGES = 5;

    @Autowired
    private EmployeeService employeeService;

    /**
     * 查询员工信息
     * 返回json数据需要导入jackson包
     *
     * @param pn
     * @return
     */
    @ResponseBody
    @RequestMapping("/emps")
    public Msg listEmpsWithJson(@RequestParam(value = "pn", defaultValue = "1") Integer pn) {
        //为了进行分页查询，引入PageHelper插件
        //在查询之前，之需要调用
        PageHelper.startPage(pn, PAGE_SIZE);
        //startPage后面紧跟的查询就是分页查询
        List<Employee> employees = employeeService.getAll();
        //使用pageInfo包装查询后的结果，之需要将pageInfo对象交给页面对象即可。
        //封装了详细的分页信息，包括有我们查询出来的数据，传入连续显示的页数
        PageInfo<Employee> page = new PageInfo<>(employees, NAVIGATE_PAGES);
        return Msg.success().add("pageInfo", page);
    }

    /**
     * 查询员工数据（分页查询）
     *
     * @param pn
     * @param model
     * @return
     */
//    @RequestMapping("/emps")
    public String listEmps(@RequestParam(value = "pn", defaultValue = "1") Integer pn, Model model) {
        //为了进行分页查询，引入PageHelper插件
        //在查询之前，之需要调用
        PageHelper.startPage(pn, PAGE_SIZE);
        //startPage后面紧跟的查询就是分页查询
        List<Employee> employees = employeeService.getAll();
        //使用pageInfo包装查询后的结果，之需要将pageInfo对象交给页面对象即可。
        //封装了详细的分页信息，包括有我们查询出来的数据，传入连续显示的页数
        PageInfo<Employee> page = new PageInfo<>(employees, NAVIGATE_PAGES);
        model.addAttribute("pageInfo", page);
        return "list";
    }

    /**
     * 保存新增用户信息
     * 1.支持JSR303
     * 2.导入hibernate-validator
     *
     * @param employee
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/emp", method = RequestMethod.POST)
    public Msg saveEmp(@Valid Employee employee, BindingResult result) {
        if (result.hasErrors()) {
            //校验失败应该返回失败，在模态框中显示校验失败的错误信息
            Map<String, String> map = new HashMap<>();
            result.getFieldErrors().forEach(e -> {
                log.info("字段{}发生校验错误，错误信息为{}", e.getField(), e.getDefaultMessage());
                map.put(e.getField(), e.getDefaultMessage());
            });
            return Msg.fail().add("errorFields", map);
        }
        employeeService.saveEmp(employee);
        log.info("save employee:{}", employee);
        return Msg.success();
    }

    /**
     * 检测用户名是否可用
     *
     * @param empName
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/checkuser", method = RequestMethod.POST)
    public Msg checkUserName(@RequestParam("empName") String empName) {
        log.info("对传入的用户名{}进行验证", empName);
        //先判断用户名是否是合法的表达式
        String regx = "(^[\\u2E80-\\u9FFF0-9]{2,5}$)|(^[a-z0-9_-]{3,16}$)";
        if (!empName.matches(regx)) {
            return Msg.fail().add("va_msg", "用户名可以是2-5位中文或者3-16位英文和数字的组合");
        }

        //数据库用户名重复校验
        boolean flag = employeeService.checkEmpUserName(empName);
        if (flag) {
            return Msg.success().add("va_msg", "用户名可用");
        } else {
            return Msg.fail().add("va_msg", "用户名不可用");
        }
    }

    /**
     * 根据员工id查询员工
     *
     * @param id
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/emp/{id}", method = RequestMethod.GET)
    public Msg getEmp(@PathVariable("id") Integer id) {
        Employee employee = employeeService.getEmployeeById(id);
        return Msg.success().add("employee", employee);
    }

    /**
     * 如果直接通过ajax发送put请求，后台接收到的Employee除了在路径中的id有值其他值都是null
     * 问题：请求体中有数据，但是Employee对象封装不上，造成mybatis在拼装sql语句出错
     * 原因：
     * 1.Tomcat：将请求体中的数据，封装一个map
     * 2.request.getParameter（'empName'）就会从这个map中取值
     * 3.SpringMVC封装POJO的时候，会把POJO中每个属性值通过request.getParameter("email")的方式获取
     * <p>
     * Ajax发送put请求引发的问题：
     * put请求，请求体中的数据，request.getParameter("empName")拿不到
     * Tomcat不会将PUT请求体中的数据封装为map，只有POST类型的请求才会将请求体中的数据封装为map
     * <p>
     * 解决方案：
     * 1.使用post请求+HiddenHttpMethodFilter方式：ajax请求方法指定为post，在data中带上&_method=PUT，这样可以通过过滤器对请求类型进行转换
     * 2.使用httpPutFormContentFilter过滤器，ajax可以直接发送put请求，springMVC会自动处理put请求的body部分，request重新被封装成一个map
     * request.getParameter（）被重写，这样就可以从中获取到POJO属性
     * <p>
     * 更新员工信息
     *
     * @param employee
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/emp/{empId}", method = RequestMethod.PUT)
    public Msg saveEmp(Employee employee) {
        log.info("save employee-{} with {}", employee.getEmpId(), employee);
        employeeService.updateEmp(employee);
        return Msg.success();
    }

    /**
     * 根据员工主键删除员工信息
     * 单个批量二合一操作
     * 批量删除：id:1-2-3-4
     * 单个删除：id：1
     *
     * @param ids
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/emp/{id}", method = RequestMethod.DELETE)
    public Msg delEmpById(@PathVariable("id") String ids) {
        log.info("删除员工-{}的信息", ids);
        if (ids.contains("-")) {
            String[] idArray = ids.trim().split("-");
            List<Integer> sid = Arrays.stream(idArray).map(Integer::parseInt).collect(Collectors.toCollection(ArrayList::new));
            employeeService.delBatchEmp(sid);
        } else {
            int eid = Integer.parseInt(ids);
            employeeService.delEmp(eid);
        }
        return Msg.success();
    }
}